package com.zx.mes.hyl.controller;


import com.zx.mes.hyl.entity.Order;
import com.zx.mes.hyl.entity.Store;
import com.zx.mes.hyl.feign.StoreServiceProvider;
import com.zx.mes.hyl.producer.TransactionListenerImpl;
import com.zx.mes.hyl.response.ObjectRestResponse;
import com.zx.mes.hyl.rocket.mq.producer.TransactionProducer;
import com.zx.mes.hyl.rocket.mq.util.RocketUtil;
import com.zx.mes.hyl.rocket.mq.yml.RocketMqProperties;
import com.zx.mes.hyl.service.OrderService;
import com.zx.mes.hyl.utils.FastJsonConvertUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author 华云龙
 * @since 2018-12-05
 */
@RestController
@RequestMapping("/order")
@Log4j2
public class OrderController extends BaseController<OrderService, Order> {

    private static final String PRODUCER_GROUP_NAME = "tx-long-order-add-producer-group-name";

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    private StoreServiceProvider storeServiceProvider;

    private TransactionProducer transactionProducer = new TransactionProducer();

    @Autowired
    private RocketMqProperties rocketMqProperties;

    /**
     * cityId,platformId,userId,supplierId,goodsId 是必需要的
     * @param order order
     * @return ObjectRestResponse
     * @throws UnsupportedEncodingException
     */
    @SuppressWarnings("JavaDoc")
    @PostMapping("/addOrder")
    public ObjectRestResponse<Order> addOrder(@RequestBody Order order) throws UnsupportedEncodingException {
        ObjectRestResponse.Builder<Order> response = new ObjectRestResponse.Builder<>();

        /// 设置UUID
        order.setOrderId(baseControllerExt.getUUID())
                .setCreateTime(LocalDateTime.now()).setUpdateTime(LocalDateTime.now())
                .setCreateBy("神做的测试").setUpdateBy("犯二");

        /// 先检测是否有贷
        /// 第一:获取订单商品库存
        ObjectRestResponse restResponse =storeServiceProvider.getByGoodIdAndSupplierId(order.getGoodsId(),order.getSupplierId());
        if (restResponse != null && restResponse.getData() != null) {
            Store store = (Store) restResponse.getData();
            if (store.getStoreCount() > 0) {
                /// 当订单商品库存大于0时允许订单
                /// 开启分布式事务
                TransactionListenerImpl listener = new TransactionListenerImpl();
                listener.setOrderService(this.biz);
                transactionProducer.producerConfig(PRODUCER_GROUP_NAME,rocketMqProperties,listener);
                RocketMqProperties.RocketMq rocketMq = RocketUtil.checkRocketMqConfig(PRODUCER_GROUP_NAME, rocketMqProperties);
                /// 消息传的是store实体类,本地消费的是带参的order
                Message message = new Message(rocketMq.getTopic(), rocketMq.getTags(), rocketMq.getKeys(), FastJsonConvertUtil.convertObjectToJSONWithNullValue(store).getBytes(RemotingHelper.DEFAULT_CHARSET));

                try {
                    TransactionSendResult result = transactionProducer.sendMessage(message, order);
                    log.debug("mq返回信息状态:" + result);
                    if (result.getSendStatus().equals(SendStatus.SEND_OK)
                            && result.getLocalTransactionState() == LocalTransactionState.COMMIT_MESSAGE) {
                        /// 1.消息发送成功,且本地事务也是成功的!
                        log.debug("事务消息发送成功!");
                        response.message("订单创建成功!");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("rocket mq 事务失败! exception:[" + e.getMessage() + "]");
                }finally {
                    /// 关闭生产者
                    this.transactionProducer.shutdown();
                }
            } else {
                /// 否则失败
                log.error("直接退出事务!");
                response.rel(false)
                        .message("创建订单失败!").
                        status(500);
            }
        }


        return response.build();
    }

    @GetMapping("/test")
    public ObjectRestResponse<Order> test(String id) {
        ObjectRestResponse response = storeServiceProvider.get(id);
        return response;
    }

}

